package com.tc.security01.config.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @Auther: tianchao
 * @Date: 2021/11/20 13:15
 * @Description:
 */
@Slf4j
public class LimitFilter extends OncePerRequestFilter implements Ordered, InitializingBean {

    private AntPathMatcher matcher = new AntPathMatcher();
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ObjectMapper objectMapper;

    private String apiRedisPrefix = "api:";



    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        log.info("[每次请求都经过这里 认证信息是:{}]", authentication);
        if (authentication == null){
            filterChain.doFilter(request, response);
            return;
        }
        User user = (User) authentication.getPrincipal();
        String username = user.getUsername();
        //查看全局开关
        if (redisTemplate.hasKey("limitEnable")){

            String url = "/user/demo";
            if (!matcher.match(url, request.getRequestURI())){
                filterChain.doFilter(request, response);
                return;
            }
            Integer minute = 1;
            Integer maxInternal = 10;
            long now = System.currentTimeMillis();
            Long count = redisTemplate.opsForZSet().count(apiRedisPrefix + username + ":" + "/user/demo", now - minute * 60 * 1000, now);
            if (count>maxInternal){
                Map<String,String> map = new HashMap<>();
                map.put("code", "111");
                map.put("msg", "限流了");
                response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                response.setCharacterEncoding("utf-8");
                response.getWriter().write(objectMapper.writeValueAsString(map));
                return;
            }
            redisTemplate.opsForZSet().add(apiRedisPrefix + username + ":" + "/user/demo", now,now);
            redisTemplate.opsForZSet().removeRangeByScore(apiRedisPrefix + username + ":" + "/user/demo", 0, now - minute * 60 * 1000);
        }
        filterChain.doFilter(request, response);

    }

    public static void main(String[] args) {
//        LimitFilter limitFilter = new LimitFilter();
//        System.out.println(limitFilter.matcher.match("tianchao:/a/b/c", "tianchao:/a/b/c"));
    }

    @Override
    public int getOrder() {
        return Integer.MAX_VALUE;
    }

    @Override
    public void afterPropertiesSet() throws ServletException {
        super.afterPropertiesSet();
    }
}
